import { each, isArray, find, filter, includes } from "lodash";
import React, { useState, useEffect } from "react";
import { Select, Radio, Space, Checkbox, List, Tree, TreeSelect } from "antd";
import { RendererPropTypes } from "@/visualizations/prop-types";
import HtmlContent from "@/components/HtmlContent";

import "./renderer.less";

export default function Renderer({ data, options, onClickHandler, refreshStartedAt }) {
  const [refreshAt, setRefreshAt] = useState(refreshStartedAt);
  const x = getColumn(options);
  const y = getColumn(options, "y");
  const parent = getColumn(options, "parent");

  function getColumn(options, axis="x") {
    var result = 'value';
    each(options.columnMapping, (type, column) => {
      if (type === axis) {
        result = column;
        return false;
      }
    });          
    return result;
  }

  let optionitems = []
  if (includes(['tree','trees','treeselect','treeselects'], options.listStyle)) {
    filter(data.rows, r => (r[parent]===undefined || r[parent]===null || r[parent]==='')).map(d => {
      const c = find(data.rows, r => r[parent] === d[x]);
      optionitems.push({
        title: d[y], 
        key: d[x], 
        isLeaf: !c,
        checkable: !c || !!options.parentCheckbox,
      });
    });
  } else {
    data.rows.map(d => optionitems.push({label: d[y], value: d[x]}));
  }
  
  function updateTreeData(list, key, children) {
    return list.map((node) => {
      if (node.key === key) {
        return { ...node, children };
      }
  
      if (node.children) {
        return { ...node, children: updateTreeData(node.children, key, children) };
      }
  
      return node;
    });
  }

  function convertData(value, col) {
    if (x===col) return value;

    if (isArray(value)) {
      var rs = new Array();
      each (value, (v) => {
        const rec = find(data.rows, r => r[x] === v);
        rs.push(rec ? rec[col] : v);
      });
      return rs;
    } else {
      const rec = find(data.rows, r => r[x] === value);
      return rec ? rec[col] : value;
    }
  }

  const onChange = value => {
    if (!options.clickEnabled) return;

    if (!!options.clickColumn) {
      var key = options.clickColumn;              
      if (!!options.clickParameter) key = options.clickParameter;

      let obj = {};
      if (!!options.quoteOption) {
        let r = [];
        let arr = value;
        if (!isArray(arr)) arr = arr.toString().split(",");
        each(arr, (v) => r.push(options.quoteOption + convertData(v, options.clickColumn).toString() + options.quoteOption));
        value = [...r];
      }
      obj[key] = convertData(value, options.clickColumn);
      onClickHandler(obj);
    }
  };
  
  const LoadTree = ({checkable=false}) => {
    const [treeData, setTreeData] = useState(optionitems);

    const onLoadData = ({ key, children }) => new Promise((resolve) => {
      if (children) {
        resolve();
        return;
      }

      setTimeout(() => {
        let items = [];
        filter(data.rows, r => r[parent] === key).map(d => {
          const c = find(data.rows, r => r[parent] === d[x])
          items.push({
            title: d[y],
            key: d[x],
            isLeaf: !c,
            checkable: !c || !!options.parentCheckbox,
          });
        });

        setTreeData((origin) => updateTreeData(origin, key, items));
        resolve();
      }, 1000);
    });

    const showPortal = window.location.search.includes("show_portal") && localStorage.getItem('colorstyle_mode');
    const cssStyle = {
      "--style-color": localStorage.getItem("colorstyle_color"),
      width: '100%',
      minWidth: '200px',
    };
    const cssStylesEdit = {
      width: '100%',
      minWidth: '200px',
    };

    var is_clear = false;
    if (!!options.clickEnabled && !!options.clickColumn) {
      const key = !!options.clickParameter ? options.clickParameter : options.clickColumn;

      is_clear = window.location.search.includes('p' + key) ? false : true;
    }
        
    if (is_clear === true) {
      return includes(['tree','trees'], options.listStyle) ? (
        <Tree 
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : cssStylesEdit}
          checkable={checkable} 
          loadData={onLoadData} 
          treeData={treeData} 
          onCheck={onChange} 
          onSelect={!checkable && onChange} 
          selectedKeys={[]}
        />
      ) : (
        <TreeSelect 
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : cssStylesEdit}
          treeCheckable={checkable ? true : false} 
          showCheckedStrategy={TreeSelect.SHOW_PARENT}
          loadData={onLoadData} 
          treeData={treeData}
          onChange={onChange}
          value={undefined}
        />
      );  
    } else {
      return includes(['tree','trees'], options.listStyle) ? (
        <Tree 
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : cssStylesEdit}
          checkable={checkable} 
          loadData={onLoadData} 
          treeData={treeData} 
          onCheck={onChange} 
          onSelect={!checkable && onChange} 
        />
      ) : (
        <TreeSelect 
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : cssStylesEdit}
          treeCheckable={checkable ? true : false} 
          showCheckedStrategy={TreeSelect.SHOW_PARENT}
          loadData={onLoadData} 
          treeData={treeData}
          onChange={onChange}
        />
      );  
    }
  };

  useEffect(() => {
    if (!!!refreshAt && !!refreshStartedAt) {
      setRefreshAt(refreshStartedAt);
    } else if (!!refreshAt && !!refreshStartedAt) {
      if (refreshAt.isBefore(refreshStartedAt)) {
        setRefreshAt(refreshStartedAt);
      }
    }
  }, [refreshStartedAt]);

  const showPortal = window.location.search.includes("show_portal") && localStorage.getItem('colorstyle_mode');
  const cssStyle = {
    "--style-color": localStorage.getItem("colorstyle_color"),
  };
  const cssStyles = {
    "--style-color": localStorage.getItem("colorstyle_color"),
    width: '100%',
    minWidth: '100px',
  };
  const cssStylesEdit = {
    width: '100%',
    minWidth: '100px',
  };
  
  let node;
  switch(options.listStyle) {
    case 'dropdown':
      node = (
        <Select
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : cssStylesEdit}
          defaultValue={data.rows.length>0 && data.rows[0][y]}
          options={optionitems}
          showSearch
          optionFilterProp="label"
          onChange={onChange} 
        />
      );
      break;
    case 'button':
      node = (
        <Radio.Group
          options={optionitems}
          onChange={e=>onChange(e.target.value)}
          defaultValue={data.rows.length>0 && data.rows[0][y]}
          optionType="button"
          buttonStyle="outline"
        />
      );
      break;
    case 'radioh':
      node = (
        <Radio.Group
          options={optionitems}
          onChange={e=>onChange(e.target.value)}
          defaultValue={data.rows.length>0 && data.rows[0][y]}
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : null}
        />
      );
      break;
    case 'radiov':
      node = (
        <Radio.Group
          onChange={e=>onChange(e.target.value)}
          defaultValue={data.rows.length>0 && data.rows[0][y]}
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : null}
        >
          <Space direction="vertical">
          {optionitems.map(item=>(
            <Radio value={item.value}>{item.label}</Radio>
          ))}
          </Space>
        </Radio.Group>
      );
      break;
    case 'dropdowns':
      node = (
        <Select
          mode="multiple"
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyles : cssStylesEdit}
          options={optionitems}
          onChange={onChange} 
          showSearch     
          optionFilterProp="label"
          allowClear   
        />
      );
      break;
    case 'checkboxsh':
      node = (
        <Checkbox.Group
          options={optionitems}
          onChange={onChange}
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : null}
        />
      );
      break;
    case 'checkboxsv':
      node = (
        <Checkbox.Group
          onChange={onChange}
          className={showPortal ? "parameter-select" : null}
          style={showPortal ? cssStyle : null}
        >
          <Space direction="vertical">
          {optionitems.map(item=>(
            <Checkbox value={item.value}>{item.label}</Checkbox>
          ))}
          </Space>
        </Checkbox.Group>
      );
      break;
    case 'tree':
    case 'treeselect':
        node = (<LoadTree />);
      break;
    case 'trees':
    case 'treeselects':
        node = (<LoadTree checkable />);
      break;
    default:
      node = (
        <List
        itemLayout="horizontal"
        dataSource={optionitems}
        className={showPortal ? "parameter-select" : null}
        style={showPortal ? cssStyle : null}
        renderItem={item => (
          <List.Item>
            <List.Item.Meta
              title={<span onClick={()=>onChange(item.value)}>{item.value}</span>}
              description={item.label}
            />
          </List.Item>
        )}
        />
      );
  }

  return (
    <>
    {options.title && (
      <div style={{display: "inline-block"}}>
        <HtmlContent>{options.title}</HtmlContent>
      </div>
    )}
    <div style={{display: "inline-block"}}>
      {node}
    </div>
    </>
  );
}

Renderer.propTypes = RendererPropTypes;
